package com.five.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.five.api.ReaderServiceAPI;
import com.five.dto.CollectionDto;
import com.five.exception.BusinessException;
import com.five.jwt.JwtUtils;
import com.five.jwt.Payload;
import com.five.jwt.RsaUtils;
import com.five.mapper.CollectionMapper;
import com.five.mapper.ReaderMapper;
import com.five.pojo.LoginInfo;
import com.five.pojo.Reader;
import com.five.producer.CollectTransactionProducer;
import com.five.result.Result;
import com.five.service.ICollectionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.net.URLDecoder;
import java.security.PublicKey;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class CollectionServiceImpl implements ICollectionService {
    @Autowired
    private CollectTransactionProducer txProducer;
    @Autowired
    private ReaderMapper readerMapper;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private CollectionMapper collectionMapper;

//    @Autowired
//    private NovelServiceAPI novelServiceAPI;

    private static final String COLLECT_KEY_PREFIX = "reader:collect:";

    /**
     * 新增收藏
     */
    @Override
    public void addCollect(String token, Long novelId) {

        LoginInfo logininfo = tokenToLoginInfo(token);

        Reader reader = readerMapper.queryByLoginInfoId(logininfo.getId());

        CollectionDto collectionDto = new CollectionDto();
        collectionDto.setReaderId(reader.getId());
        collectionDto.setNovelId(novelId);

        if (StringUtils.isEmpty(novelId)) {
            throw new BusinessException("收藏的图书不能为空...");
        }
//        Long novel=novelServiceAPI.selectById(novelId);
//        if(novel==null){
//            throw new BusinessException("没有该书籍...");
//        }

        // 2. 调用事务消息生产者，触发Redis写入+消息发送
        txProducer.sendAddCollectTxMsg(collectionDto);
    }

    /**
     * 取消收藏
     */
    @Override
    public void cancelCollect(String token, Long novelId) {
        LoginInfo logininfo = tokenToLoginInfo(token);

        Reader reader = readerMapper.queryByLoginInfoId(logininfo.getId());

        CollectionDto collectionDto = new CollectionDto();
        collectionDto.setReaderId(reader.getId());
        collectionDto.setNovelId(novelId);

        if (StringUtils.isEmpty(novelId)) {
            throw new BusinessException("取消收藏的图书不能为空...");
        }
//        Long novel=novelServiceAPI.selectById(novelId);
//        if(novel==null){
//            throw new BusinessException("没有该书籍...");
//        }

        // 2. 调用事务消息生产者，触发Redis写入+消息发送
        txProducer.sendCancelCollectTxMsg(collectionDto);
    }

    /**
     * 从Redis获取读者收藏的书籍ID
     * @return 书籍ID集合
     */
    @Override
    public Set<Long> getReaderCollectNovelIds(String token) {
        LoginInfo logininfo = tokenToLoginInfo(token);

        Reader reader = readerMapper.queryByLoginInfoId(logininfo.getId());
        Long readerId = reader.getId();

        if (readerId == null) {
            throw new BusinessException("未登录，请登陆后查看...");
        }
        String redisKey = COLLECT_KEY_PREFIX + readerId;

        List<Long> novelIds = collectionMapper.getNovelIdByReaderId(readerId);
        novelIds.forEach(novelId -> {
            if (novelId == null) {
                throw new BusinessException("收藏的图书ID不能为空...");
            }
            redisTemplate.opsForSet().add(redisKey, String.valueOf(novelId));
        });

        // 构建Redis键
        // 从Redis的Set集合中获取所有书籍ID（存储的是字符串类型，需转换为Long）
        Set<Object> novelIdStrs = redisTemplate.opsForSet().members(redisKey);

        // 转换为Long类型集合（空集合返回空Set，避免null）
        return novelIdStrs.stream()
                .map(idStr -> Long.valueOf(idStr.toString()))
                .collect(Collectors.toSet());
    }


    /*
    * 根据token获取登录人信息
    * */
    public LoginInfo tokenToLoginInfo(String token) {
        PublicKey publicKey;
        LoginInfo logininfo;
        try {
            publicKey = RsaUtils.getPublicKey(URLDecoder.decode(
                    JwtUtils.class.getClassLoader().getResource("hrm_auth_rsa.pub").getFile(), "UTF-8"));
            Payload<Map> payload = JwtUtils.getInfoFromToken(token, publicKey, Map.class);
            // 4. 获取"loginInfo"对应的JSON对象，并转换为LoginInfo
            Object loginInfoObj = payload.getUserInfo().get("loginInfo");
            // 关键：使用FastJSON将JSON对象反序列化为LoginInfo（核心解决类型转换问题）
            logininfo = JSON.toJavaObject((JSONObject) loginInfoObj, LoginInfo.class);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return logininfo;
    }
}